package cn.kow.kmall.controller.system;

import cn.kow.kmall.controller.BaseController;
import cn.kow.kmall.core.response.KmallResult;
import cn.kow.kmall.system.entity.SysMenu;
import cn.kow.kmall.system.entity.SysRole;
import cn.kow.kmall.admin.pojo.dto.MenuQueryDTO;
import cn.kow.kmall.admin.pojo.vo.MenuVO;
import cn.kow.kmall.admin.pojo.vo.RouterVO;
import cn.kow.kmall.admin.pojo.vo.TreeSelectVO;
import cn.kow.kmall.system.service.SysMenuService;
import cn.kow.kmall.system.service.SysRoleService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: lijun
 * @Description:
 * @Date: Created in 2019-10-29 17:04
 * @Modified By:
 */
@Slf4j
@RestController
@RequestMapping("/menu")
public class SysMenuController extends BaseController {

    @Autowired
    private SysMenuService menuService;

    @Autowired
    private SysRoleService roleService;

    /**
     * 新增菜单
     * @param menu  菜单
     * @return 结果
     */
    @PostMapping(value = "/add")
    public KmallResult add(@RequestBody SysMenu menu) {
        String userName = currentUser().getUsername();
        menu.setCreateBy(userName);
        menu.setUpdateBy(userName);
        menuService.save(menu);
        return KmallResult.success();
    }

    /**
     * 删除菜单
     * @param menuId  菜单ID
     * @return 结果
     */
    @DeleteMapping("/{menuId}")
    public KmallResult remove(@PathVariable Long menuId) {
        menuService.remove(menuId);
        return KmallResult.success();
    }

    /**
     * 修改菜单
     * @param menu  菜单
     * @return 结果
     */
    @PostMapping(value = "/edit")
    public KmallResult edit(@RequestBody SysMenu menu) {
        menu.setUpdateBy(currentUser().getUsername());
        menuService.update(menu);
        return KmallResult.success();
    }

    /**
     * 查看菜单
     * @param menuId  菜单ID
     * @return 结果
     */
    @GetMapping(value = "/{menuId}")
    public KmallResult view(@PathVariable Long menuId) {
        SysMenu menu = menuService.getById(menuId);
        return KmallResult.success(toMenuVO(menu));
    }

    /**
     * 获取菜单列表
     */
    @RequestMapping(value = "/route")
    public KmallResult route() {
        List<SysMenu> menuList = menuService.listMenuByUser(currentUser());
        List<SysMenu> pList = menuList.stream().filter(m -> m.getParentId() == 0).collect(Collectors.toList());
        Map<Long, List<SysMenu>> menuMap = menuList.stream().filter(m -> m.getParentId() != 0).collect(Collectors.groupingBy(SysMenu::getParentId));
        List<RouterVO> routerList = buildRouter(pList, menuMap);
        return KmallResult.success().put("routeList", routerList);
    }

    private List<RouterVO> buildRouter(List<SysMenu> menuList, Map<Long, List<SysMenu>> menuMap) {
        List<RouterVO> routerList = new LinkedList<>();
        for (SysMenu menu : menuList) {
            RouterVO router = new RouterVO();
            if (0 == menu.getParentId() && 1 == menu.getIsFrame()) {
                router.setPath("/" + menu.getPath());
            } else {
                router.setPath(menu.getPath());
            }
            router.setName(StringUtils.capitalize(menu.getPath()));
            router.setComponent(menu.getComponent());
            router.setMeta(router.new Meta(menu.getMenuName(), menu.getIcon()));
            router.setHidden(0 == menu.getVisible());
            List<SysMenu> cMenus = menuMap.get(menu.getId());
            if (CollectionUtils.isNotEmpty(cMenus) && "M".equals(menu.getMenuType()))
            {
                router.setAlwaysShow(true);
                router.setRedirect("noRedirect");
                router.setChildren(buildRouter(cMenus, menuMap));
            }
            routerList.add(router);
        }
        return routerList;
    }

    /**
     * 获取菜单列表
     */
    @PostMapping(value = "/list")
    public KmallResult list(@RequestBody MenuQueryDTO queryDTO) {
        List<SysMenu> menuList = menuService.listMenu(queryDTO);
        return KmallResult.success().put("rows", toVOList(menuList));
    }

    /**
     * 获取菜单列表
     */
    @GetMapping(value = "/list/tree")
    public KmallResult treeList() {
        MenuQueryDTO queryDTO = new MenuQueryDTO();
        queryDTO.setMenuType("M");
        List<SysMenu> menuList = menuService.listMenu(queryDTO);
        List<MenuVO> voList = toVOList(menuList);
        return KmallResult.success().put("list", voList.stream().map(TreeSelectVO::new).collect(Collectors.toList()));
    }

    /**
     * 获取菜单列表
     */
    @GetMapping(value = "/list/tree/role/{roleId}")
    public KmallResult treeListWithRole(@PathVariable Long roleId) {
        MenuQueryDTO queryDTO = new MenuQueryDTO();
        List<SysMenu> menuList = menuService.listMenu(queryDTO);

        // 查询角色对应的菜单
        SysRole sysRole = roleService.getById(roleId);
        List<Long> menuIds = new ArrayList<>();
        if (null != sysRole) {
            List<SysMenu> menus = sysRole.getMenus();
            if (!org.springframework.util.CollectionUtils.isEmpty(menus)) {
                menus.stream().forEach(m -> menuIds.add(m.getId()));
            }
            Map<Long, Set<Long>> menuIdMap = menuList.stream().filter(m -> m.getParentId() != 0)
                    .collect(Collectors.groupingBy(SysMenu::getParentId, Collectors.mapping(SysMenu::getId, Collectors.toSet())));
            Iterator<Long> iterator = menuIds.iterator();
            while (iterator.hasNext()) {
                Long id = iterator.next();
                if (menuIdMap.containsKey(id) && CollectionUtils.isNotEmpty(menuIdMap.get(id))) {
                    iterator.remove();
                }
            }
        }

        List<MenuVO> voList = toVOList(menuList);
        return KmallResult.success()
                .put("list", voList.stream().map(TreeSelectVO::new).collect(Collectors.toList()))
                .put("checkedKeys", menuIds);
    }

    private List<MenuVO> toVOList(List<SysMenu> menuList) {
        Map<Long, List<SysMenu>> menuMap = menuList.stream().filter(m -> m.getParentId() != 0).collect(Collectors.groupingBy(SysMenu::getParentId));
        List<SysMenu> firstLevelMenus = menuList.stream().filter(m -> m.getParentId() == 0).collect(Collectors.toList());
        List<MenuVO> menuVOList = firstLevelMenus.stream().map(m -> toMenuVO(m)).collect(Collectors.toList());
        setSubMenus(menuVOList, menuMap);
        return menuVOList;
    }

    private void setSubMenus(List<MenuVO> menuVOList, Map<Long, List<SysMenu>> menuMap) {
        for (MenuVO menuVO : menuVOList) {
            if (menuMap.containsKey(menuVO.getId())) {
                List<MenuVO> subMenuList = menuMap.get(menuVO.getId()).stream().map(m -> toMenuVO(m)).collect(Collectors.toList());
                menuVO.setChildren(subMenuList);
                setSubMenus(subMenuList, menuMap);
            }
        }
    }

    private MenuVO toMenuVO(SysMenu menu) {
        MenuVO vo = new MenuVO();
        BeanUtils.copyProperties(menu, vo);
        vo.setId(menu.getId());
        vo.setChildren(new ArrayList<>());
        return vo;
    }
}

